
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "Int.h"

static int Integer_Shift_32(Integer *in,Integer *out,int dir,int n);

#define INT_SIZE 32
#define Integer_LeftShift 0
#define Integer_RightShift 1


static int test(int argc,char **argvs)
{
	int i = 0,co;
	Integer *sum = NULL,*new = NULL;
	double aaa = 1;
	
	while(i < 36) {
	    aaa = aaa * 2;
		i = i + 1;		
	}
	printf("%lf\n",aaa);
	sum = Integer_Init(13);
	Print_Integer(sum);
	Integer_SetOne(sum);
	Print_Integer(sum);
	Integer_Shift(sum,sum,Integer_LeftShift,13);
	Print_Integer(sum);
	new = Integer_Init(13);
	Integer_Multi(sum,0.0007, new);
	Print_Integer(new);
	Integer_Free(new);
	exit(0);
	Integer_Dup(sum,&new);
	Print_Integer(new);
	Integer_Shift(new,new,Integer_RightShift,10);
	while(i < 60) {
		
		Integer_Shift(sum,sum,Integer_RightShift,1);
		Integer_Add(sum,new,sum,&co);
		Print_Integer(sum);
		i = i + 1;
	}
	/*2^(-k)<10^(-s);
	k>(1+log_2^5)*s;
	k>(3.321928)*s;
	k>=(int)((3.321928)*s)*/
	double aa = (double)Get_13(sum);
	printf("%lf\n",aa/(0x01<<13));
	//Print_13(Get_13(sum));
	Integer_Free(sum);
	//Integer_Free(new);
	return 0;
}

//最低位置1
extern int Integer_SetOne(Integer *in)
{
	in->vec[0] = in->vec[0] + 0x01;
	return 1;
}

extern int Integer_Dup(Integer *src,Integer **des)
{
	int i = 0;
	*des = Integer_Init_fast(src->length,src->size);
	while(i < src->size) {
		(*des)->vec[i] = src->vec[i];
		i = i + 1;
	}
	
	return 1;
}

//移位
extern int Integer_Shift(Integer *in,Integer *out,int dir,int n)
{
	int nsize = 0,nbits = 0,i = 0;
	nsize = n/31;
	nbits = n%31;
	i = 0;
	while(i < nsize) {
		Integer_Shift_32(in,out,dir,31);
		in = out;
		i= i + 1;
	}
	Integer_Shift_32(in,out,dir,nbits);
	return 0;
}

static int Integer_Shift_32(Integer *in,Integer *out,int dir,int n)
{
	int i = 0,tmp_h = 0,tmp_l = 0;
	if(dir == Integer_LeftShift) {
		i = in->size - 1;
		while(i >= 0) {
			if((i + 1) < in->size) {
				out->vec[i + 1] = out->vec[i + 1] | (in->vec[i]>>(INT_SIZE - n));
			}
			out->vec[i] = in->vec[i]<<n;
			i = i - 1;
		}
	}
	else {
		i = 0;
		while(i < in->size) {
			if(i != 0) {
				out->vec[i - 1] = out->vec[i - 1] | in->vec[i]<<(INT_SIZE - n);
			}
			out->vec[i] = in->vec[i]>>n;
			i = i + 1;
		}
	}
	return 0;
}

extern int Integer_Add(Integer *a,Integer *b,Integer *sum, int *co)
{
	int i = 0,ci_tmp = 0,co_tmp = 0;
	unsigned int tmp_a = 0,tmp_b = 0,tmp_sum = 0;
	if(a->size != b->size) {
		return 0;
	}
	while(i < a->size) {
		ci_tmp = co_tmp;
		tmp_a = a->vec[i];
		tmp_b = b->vec[i];
		tmp_sum = tmp_a + tmp_b + ci_tmp;
		//溢出
		if((tmp_sum < tmp_a) && (tmp_sum < tmp_b)) {
			co_tmp = 1;
		}
		else {
			co_tmp = 0;
		}
		sum->vec[i] = tmp_sum;
		i = i + 1;
	}
	*co = co_tmp;
	return 1;
}

extern Integer * Integer_Init(int length)
{
	Integer *integer1 = NULL; 
	int i = 0;
	integer1 = (Integer *)malloc(sizeof(Integer));
	integer1->length = length;
	integer1->size = (integer1->length - 1)/INT_SIZE + 1;
	if(integer1->length%INT_SIZE == 0) {
		//预留
		integer1->size = integer1->size + 1;
	}
    integer1->vec = (unsigned int *)malloc(sizeof(unsigned int)*integer1->size);
	//置0
	i = 0;
	while(i < integer1->size) {
		integer1->vec[i] = 0;
		i = i + 1;
	}
	
    return integer1;
}	

extern Integer * Integer_Init_fast(int length,int size)
{
	Integer *integer1 = NULL; 
	int i = 0;
	integer1 = (Integer *)malloc(sizeof(Integer));
	integer1->length = length;
	integer1->size = size;
    integer1->vec = (unsigned int *)malloc(sizeof(unsigned int)*integer1->size);
	//置0
	memset(integer1->vec,0,sizeof(unsigned int)*integer1->size);
    return integer1;
}	

extern int Integer_Free(Integer* integer1)
{
	free(integer1->vec);
	free(integer1);
	return 0;
}


//获取高13位
extern unsigned int Get_13(Integer* sum)
{
    int count = 0;
	unsigned int value = 0;
	int i = sum->size - 1;
	int j = sum->length%INT_SIZE;	//j = (sum->length + 1 - 1)%INT_SIZE;
	while(i >= 0) {
		while(j >= 0) {
			if((count>0)&&(count<14)) {
				if((sum->vec[i] & (0x01<<j)) == 0) {
					value = value<<1;
				}
				else {
					value = (value<<1) + 1;
				}
				
			}
			count = count + 1;
			j = j - 1;
		}
		j = INT_SIZE - 1;
		i = i - 1;
	}
	return value;
}

//打印
extern unsigned int Print_13(unsigned int value)
{
    int count = 0;
	int i = 12;
	while(i >= 0) {
		if((value & (0x01<<i)) == 0) {
			printf("0");
		}
		else {
			printf("1");
		}
		i = i - 1;
	}
	printf("\n");
	return 0;
}


extern int Print_Integer(Integer* sum)
{
	int i = sum->size - 1;
	int j = sum->length%INT_SIZE;	//j = (sum->length + 1 - 1)%INT_SIZE;
	while(i >= 0) {
		while(j >= 0) {
			if((sum->vec[i] & (0x01<<j)) == 0) {
				printf("0");
			}
			else {
				printf("1");
			}
			j = j - 1;
		}
		printf(" ");
		j = INT_SIZE - 1;
		i = i - 1;
	}
	printf("\n");
	return 0;
}

//比较大小
extern int Integer_Compare(Integer *a,Integer *b)
{
	int i = 0, flag = 0; //flag = 0 表示a=b，flag = 1表示a > b，flag = -1表示 a < b
	i = a->size - 1;
	while(i >= 0) {
		if(a->vec[i] > b->vec[i]) {
			flag = 1;
			break;
		}
		else if(a->vec[i] < b->vec[i]) {
			flag = -1;
			break;
		}
		else if(a->vec[i] == b->vec[i]) {
			i = i - 1;
		}
		
	}
	
	return flag;
}

//比例,一个大数乘以一个小数，精度为0.01%
extern int Integer_Multi(Integer *a, double p, Integer *product)
{
	if(a->length > 13) {
		Integer_Shift(a, product, Integer_RightShift, a->length - 13);
		product->vec[0] = (unsigned int)(product->vec[0] * p);
		Integer_Shift(product, product, Integer_LeftShift, a->length - 13);
	}
	else {
		product->vec[0] = (unsigned int)(a->vec[0] * p);
	}	
	
	return 0;
}


